package com.jinxin.phonecloudmusic.myapplication.net;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jinxin.phonecloudmusic.myapplication.utils.L;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * Created by icarus.lee on 2017/6/26.
 */

public class NetUtil {

    private static NetUtil netUtil;
    private int timeout = 20;
    public static final String baseUrl = "http://www.beonehome.com:6100/smarthome/m-m/music3?";//云平台(获取数据)
    //    public static final String baseUrl = NetConsts.HEBEI_TEST;
    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
    private static final MediaType MEDIA_TYPE_JPG = MediaType.parse("image/jpg");
    private static final MediaType MEDIA_TYPE_FILE = MediaType.parse("application/octet-stream");

    private NetUtil() {

    }

    public synchronized static NetUtil getInstance() {
        if (netUtil == null) {
            netUtil = new NetUtil();
        }
        return netUtil;
    }


    /**
     * 异步get请求,根据NetRequest对象请求网络,如果t 为null则回调netCallback对象的onResponse(String data)方法,
     * 否则调用onResponse(List<T> data)方法,List中的元素为T类型
     *
     * @param t           设置返回的List中元素类型,如果传入null,则返回String类型,并回调onResponse(String data)方法
     * @param netRequest  包含网络请求信息的对象
     * @param netCallback 处理返回数据的对象
     */
    public <T> void asyGet(final NetRequest netRequest, final Class<T> t, final NetCallback<T> netCallback) {
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        String url;
        if (netRequest.getUrl() != null) {
            url = netRequest.getUrl();
        } else {
            url = baseUrl;
        }
        builder.url(url + "?$data=" + netRequest.getRequestBody());
        builder.method("GET", null);
        Call call = okHttpClient.newCall(builder.build());
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                L.e("请求数据超时!");
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) {
                ResponseBody body = response.body();
                try {
                    String resData = body.string();
                    JSONObject jo = JSON.parseObject(resData);
                    if (jo != null && jo.containsKey("response")) {
                        JSONObject resJo = jo.getJSONObject("response");
                        String rspCode = resJo.getString("rspCode");
                        if (rspCode.equals("0000")) {
                            String data = jo.getString("serviceContent");
                            if (t != null) {
                                List<T> list = JSON.parseArray(data, t);
                                netCallback.onResponse(list);
                            } else {
                                netCallback.onResponse(data);
                            }
                        } else {
                            netCallback.onFailure(rspCode);
                            L.e("请求数据失败! rspCode:" + rspCode);
                        }
                    } else {
                        L.e("返回数据格式错误!");
                    }
                } catch (IOException e) {
                    L.d("服务器连接异常!");
                    e.printStackTrace();
                }
            }
        });
    }


    /**
     * 异步post请求,根据NetRequest对象请求网络,如果t 为null则回调netCallback对象的onResponse(String data)方法,
     * 否则调用onResponse(List<T> data)方法,List中的元素为T类型
     *
     * @param t           设置返回的List中元素类型,如果传入null,则返回String类型,并回调onResponse(String data)方法
     * @param netRequest  包含网络请求信息的对象
     * @param netCallback 处理返回数据的对象
     */
    public <T> void synPost(final NetRequest netRequest, final Class<T> t, final NetCallback<T> netCallback) {
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        String url;
        if (netRequest.getUrl() != null) {
            url = netRequest.getUrl();
        } else {
            url = baseUrl;
        }
        builder.url(url);
        FormBody formBody = new FormBody.Builder()
                .add("$data", netRequest.getRequestBody())
                .build();
        builder.method("POST", formBody);
        Call call = okHttpClient.newCall(builder.build());
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                L.e("请求数据超时!");
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) {
                ResponseBody body = response.body();
                try {
                    String resData = body.string();
                    JSONObject jo = JSON.parseObject(resData);
                    if (jo != null && jo.containsKey("response")) {
                        JSONObject resJo = jo.getJSONObject("response");
                        String rspCode = resJo.getString("rspCode");
                        if (rspCode.equals("0000")) {
                            L.i("jo====" + jo.toJSONString());
                            String data = jo.getString("serviceContent");
                            if (t != null) {
                                List<T> list = JSON.parseArray(data, t);
                                netCallback.onResponse(list);
                            } else {
                                netCallback.onResponse(data);
                            }
                        } else {
                            netCallback.onFailure(rspCode);
                            L.e("请求数据失败! rspCode:" + rspCode);
                        }
                    } else {
                        L.e("返回数据格式错误!");
                    }
                } catch (IOException e) {
                    L.d("服务器连接异常!");
                    e.printStackTrace();
                }
            }
        });
    }


    /**
     * 同步get请求,根据NetRequest对象请求网络,
     *
     * @param t          设置返回的List中元素类型
     * @param netRequest 包含网络请求信息的对象
     * @return 根据返回结果提取出的List<T>对象
     */
    public <T> List<T> get(final NetRequest netRequest, final Class<T> t) {
        List<T> list = null;
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        String url;
        if (netRequest.getUrl() != null) {
            url = netRequest.getUrl();
        } else {
            url = baseUrl;
        }
        builder.url(url + "?$data=" + netRequest.getRequestBody());
        builder.method("GET", null);
        Call call = okHttpClient.newCall(builder.build());
        try {
            Response response = call.execute();
            String resData = response.body().string();
            JSONObject jo = JSON.parseObject(resData);
            if (jo != null && jo.containsKey("response")) {
                JSONObject resJo = jo.getJSONObject("response");
                String rspCode = resJo.getString("rspCode");
                if (rspCode.equals("0000")) {
                    list = JSONArray.parseArray(jo.getString("serviceContent"), t);
                } else {
                    L.e("请求数据失败! rspCode:" + rspCode);
                }
            } else {
                //L.e("返回数据格式错误! bipCode:" + netRequest.getRequestValues().getBipCode() + " activityCode:" + netRequest.getRequestValues().getActionCode());
            }

        } catch (IOException e) {
            L.d("服务器连接异常!");
            e.printStackTrace();
        }
        return list;
    }


    /**
     * 同步get请求,根据NetRequest对象请求网络,
     *
     * @param netRequest 包含网络请求信息的对象
     * @return 返回服务器json中的serviceContent 的value字符串
     */
    public JSONObject get(final NetRequest netRequest) {
        JSONObject resultJo = new JSONObject();
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        String url;
        if (netRequest.getUrl() != null) {
            url = netRequest.getUrl();
        } else {
            url = baseUrl;
        }
        builder.url(url + "$data=" + netRequest.getRequestBody().replace("\\\\","\\"));
        builder.method("GET", null);
        Call call = okHttpClient.newCall(builder.build());
        try {
            Response response = call.execute();
            String resData = response.body().string();
            //这里云音乐返回的数据格式不正确
            String n=resData.substring(resData.indexOf("(") + 1, resData.lastIndexOf(")"));
            JSONObject jo = JSON.parseObject(n);
            if (jo != null /*&& jo.containsKey("response")*/) {
                /*JSONObject resJo = jo.getJSONObject("response");
                resultJo.put("rspCode", resJo.getString("rspCode"));*/
                resultJo.put("serviceContent", jo/*.getString("serviceContent")*/);
            } else {
                //L.e("返回数据格式错误! bipCode:" + netRequest.getRequestValues().getBipCode() + " activityCode:" + netRequest.getRequestValues().getActionCode());
            }

        } catch (IOException e) {
            L.d("服务器连接异常!");
            e.printStackTrace();
        }
        return resultJo;
    }


    /**
     * 同步post请求,根据NetRequest对象请求网络
     *
     * @param t          设置返回的List中元素类型
     * @param netRequest 包含网络请求信息的对象
     * @return 根据返回结果提取出的List<T>对象
     */
    public <T> List<T> post(final NetRequest netRequest, final Class<T> t) {
        List<T> list = null;
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        String url;
        if (netRequest.getUrl() != null) {
            url = netRequest.getUrl();
        } else {
            url = baseUrl;
        }
        builder.url(url);
        FormBody formBody = new FormBody.Builder()
                .add("$data", netRequest.getRequestBody())
                .build();
        builder.method("POST", formBody);
        Call call = okHttpClient.newCall(builder.build());
        try {
            Response response = call.execute();
            String resData = response.body().string();
            JSONObject jo = JSON.parseObject(resData);
            if (jo != null && jo.containsKey("response")) {
                JSONObject resJo = jo.getJSONObject("response");
                String rspCode = resJo.getString("rspCode");
                if (rspCode.equals("0000")) {
                    list = JSONArray.parseArray(jo.getString("serviceContent"), t);
                } else {
                    L.e("请求数据失败! rspCode:" + rspCode);
                }
            } else {
                //L.e("返回数据格式错误! bipCode:" + netRequest.getRequestValues().getBipCode() + " activityCode:" + netRequest.getRequestValues().getActionCode());
            }

        } catch (IOException e) {
            L.d("服务器连接异常!");
            e.printStackTrace();
        }
        return list;
    }


    /**
     * 同步post请求,根据NetRequest对象请求网络,
     *
     * @param netRequest 包含网络请求信息的对象
     * @return 返回服务器json中的serviceContent 的value字符串
     */
    public JSONObject post(final NetRequest netRequest) {
        JSONObject resultJo = new JSONObject();
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        String url;
        if (netRequest.getUrl() != null) {
            url = netRequest.getUrl();
        } else {
            url = baseUrl;
        }
        builder.url(url);
        FormBody formBody = new FormBody.Builder()
                .add("$data", netRequest.getRequestBody())
                .build();
        builder.method("POST", formBody);
        Call call = okHttpClient.newCall(builder.build());
        try {
            Response response = call.execute();
            String resData = response.body().string();
            JSONObject jo = JSON.parseObject(resData);
            if (jo != null && jo.containsKey("response")) {
                JSONObject resJo = jo.getJSONObject("response");
                resultJo.put("rspCode", resJo.getString("rspCode"));
                resultJo.put("serviceContent", jo.getString("serviceContent"));
            } else {
                //L.e("返回数据格式错误! bipCode:" /*+ netRequest.getRequestValues().getBipCode() + " activityCode:" + netRequest.getRequestValues().getActionCode()*/);
            }

        } catch (IOException e) {
            L.d("服务器连接异常!");
            e.printStackTrace();
        }
        return resultJo;
    }


    /**
     * 同步post请求,参数请求网络,并提交图片
     */
    public JSONObject post(String url, Map<String, Object> values, String fileName, File zipFile) {
        JSONObject resultJo = new JSONObject();
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
        multipartBodyBuilder.setType(MultipartBody.FORM);
        //添加参数
        for (Map.Entry<String, Object> entry : values.entrySet()) {
            multipartBodyBuilder.addFormDataPart(entry.getKey(), entry.getValue().toString());
        }
        //添加图片
        if (zipFile!=null){
            multipartBodyBuilder.addFormDataPart("file", fileName,RequestBody.create(MEDIA_TYPE_FILE,zipFile));
        }
        RequestBody requestBody = multipartBodyBuilder.build();
        builder.method("POST", requestBody);
        Call call = okHttpClient.newCall(builder.build());
        try {
            Response response = call.execute();
            String resData = response.body().string().toString();
            JSONObject jo = JSONObject.parseObject(resData);
            if (jo != null) {
                resultJo = jo;
                L.i(jo.toJSONString());
            } else {

            }
        } catch (IOException e) {
            L.d("服务器连接异常!");
            e.printStackTrace();
            return null;
        }
        return  resultJo;
    }


    /**
     * 用于请求外网其它服务器
     *
     * @param url
     * @return 服务器返回的原始数据
     */
    public String get(String url) {
        String resData = "";
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.method("GET", null);
        Call call = okHttpClient.newCall(builder.build());
        Response response = null;
        try {
            response = call.execute();
            resData = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resData;
    }

    /**
     * 用于请求外网其它服务器
     *
     * @param url
     * @return 服务器返回的原始数据
     */
    public String post(String url) {
        String resData = "";
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.method("POST", null);
        Call call = okHttpClient.newCall(builder.build());
        Response response = null;
        try {
            response = call.execute();
            resData = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resData;
    }


    public void opinionsPost(String url, Map<String, Object> map, Callback callback) {
        OkHttpClient okHttpClient = new OkHttpClient();
        FormBody.Builder builder = new FormBody.Builder();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            builder.add(entry.getKey(), (String) entry.getValue());
        }
        Request request = new Request.Builder()
                .url(url)
                .post(builder.build())
                .build();
        okHttpClient.newCall(request).enqueue(callback);
    }

}
